package Jogador;

import java.util.Random;
import java.util.Scanner;

import Posicao.Posicao;
import Posicao.PosicaoCollection;
import Tabuleiro.Tabuleiro;

public class JogadorPC implements JogadorIF {
	private int bombasDescobertas = 0;
	private String nome = "";
	
	public JogadorPC(String nome) {
		this.setNome(nome);
	}
	
	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getNome() {
		return this.nome;
	}

	public void setBombasDescobertas(int bombasDescobertas) {
		this.bombasDescobertas = bombasDescobertas;
	}
	
	public int getBombasDescobertas() {
		return this.bombasDescobertas;
	}
	
	public Posicao jogada(Tabuleiro tabuleiro) {
		Posicao sorteio = new Posicao(0,0);
		System.out.println("PC: Procurando casas incompletas...");
		if(this.getDisponibilidadeCasasIncompletas(tabuleiro)) {
			sorteio = this.sorteiaAdjacenciaCasaIncompleta(tabuleiro);
			if(sorteio != null) {
				System.out.println("\nPC: Escolhi a casa de posicao "+(sorteio.getX()+1)+"."+(sorteio.getY()+1)+"! [ENTER]");
				this.hold();
				return sorteio;
			}
		} else {
			System.out.println("PC: Nada!");
			System.out.println("PC: Procurando casas completas e jogaveis...");
		}
		if(this.getDisponibilidadeCasasCompletasJogaveis(tabuleiro)) {
			sorteio = this.sorteiaAdjacenciaCasaCompleta(tabuleiro);
			if(sorteio != null) {
				System.out.println("\nPC: Escolhi a casa de posicao "+(sorteio.getX()+1)+"."+(sorteio.getY()+1)+"! [ENTER]");
				this.hold();
				return sorteio;
			}
		} {
			System.out.println("PC: Nada!");
			System.out.println("PC: Escolhendo uma casa nao identificada qualquer...");
		}
		return this.jogadaF(tabuleiro);
	}
	

	
	public String toString() {
		return this.nome + " " + this.bombasDescobertas;
	}

	public Posicao jogadaF(Tabuleiro tabuleiro) { //NIVEL FACIL!
		Posicao posicao = new Posicao(-1,-1);
		Random numeroRandomico = new Random(); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Codigo repetido(JogadorPC e Tabuleiro)
		int x = numeroRandomico.nextInt(tabuleiro.getTamanho()); //gera um inteiro randomico de 0 a tabuleiro.tamanho-1;
		int y = numeroRandomico.nextInt(tabuleiro.getTamanho());
		boolean ok = false;
		do {
			if(tabuleiro.getCasa(x, y).getIdentificada()) {
				x = numeroRandomico.nextInt(tabuleiro.getTamanho());
				y = numeroRandomico.nextInt(tabuleiro.getTamanho());
			}
			else ok = true;
		} while(!ok);
		posicao.setX(x);
		posicao.setY(y);
		System.out.println("\nPC: Escolhi a casa de posicao "+(posicao.getX()+1)+"."+(posicao.getY()+1)+"! [ENTER]");
		this.hold();
		return posicao;
	}
	
	private void hold() {
		Scanner sc = new Scanner(System.in);
		sc.nextLine();
	}
	
	public boolean getDisponibilidadeCasasIncompletas(Tabuleiro tabuleiro) {
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(/*!tabuleiro.getCasa(i, j).getBomba() && */tabuleiro.getCasa(i, j).getIdentificada() && !this.getCompletude(i, j, tabuleiro)) return true; //verificar condicao pra completude 
			}
		}
		return false;
	}

	private boolean getCompletude(int linha, int coluna, Tabuleiro tabuleiro) {
		if(!tabuleiro.getCasa(linha, coluna).getIdentificada()) return false;
		if(tabuleiro.getCasa(linha, coluna).getBomba()) return true;
		int numeroBombasIdentificadas = 0; //numero de bombas adjacentes a casa(linha,coluna) identificadas;
		for (int i = linha-1; i < linha+2; i++) {
			for (int j = coluna-1; j < coluna+2; j++) {
				if(i != linha || j != coluna) { //nao conta as adjacencias de casa(linha,coluna)
					if(tabuleiro.verificaValor(i) && tabuleiro.verificaValor(j) && tabuleiro.getCasa(i, j).getBomba() && tabuleiro.getCasa(i, j).getIdentificada()) numeroBombasIdentificadas++; 
				}
			}
		}
		return (numeroBombasIdentificadas == tabuleiro.getCasa(linha, coluna).getNumeroBombasAdjacentes());
	}

	public boolean getDisponibilidadeCasasCompletasJogaveis(Tabuleiro tabuleiro) {
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(this.getCompletude(i, j, tabuleiro)) {
					if(this.getJogavelAdjacente(i,j, tabuleiro)) return true;
				}
			}
		}
		return false;
	}
	
	/*
	 * Verifica se existe alguma casa nao identificada adjacente a casa(linha, coluna)
	 */
	private boolean getJogavelAdjacente(int linha, int coluna, Tabuleiro tabuleiro) {
		for (int i = linha-1; i < linha+2; i++) {
			for (int j = coluna-1; j < coluna+2; j++) {
				if(i != linha || j != coluna) { //pula a analise da casa(linha,coluna)
					if(tabuleiro.verificaValor(i) && tabuleiro.verificaValor(j) && !tabuleiro.getCasa(i, j).getIdentificada()) return true; 
				}
			}
		}
		return false;
	}

	public Posicao getMaiorPosicaoMaiorCasaIncompleta(Tabuleiro tabuleiro) {
		Posicao posicaoBase = new Posicao(-1, -1);
		posicaoBase = this.getPosicaoIncompleta(tabuleiro);
		if(posicaoBase == null) return posicaoBase;
		int x = posicaoBase.getX();
		int y = posicaoBase.getY();
		System.out.println("PC: Achei uma casa na posicao "+(x+1)+"."+(y+1)+"...");
		System.out.println("PC: Procurando outra casa incompleta com maior adjacencia...");
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(i != x || j != y) {
					if(tabuleiro.getCasa(i, j).getIdentificada() && !this.getCompletude(i, j, tabuleiro) && (tabuleiro.getCasa(i, j).getNumeroBombasAdjacentes() > tabuleiro.getCasa(posicaoBase.getX(), posicaoBase.getY()).getNumeroBombasAdjacentes())) {
						posicaoBase.setX(i);
						posicaoBase.setY(j);
					}
				}
			}
		}
		if(posicaoBase.getX() == x && posicaoBase.getY() == y) System.out.println("PC: Aff! Nao encontrei...");
		else System.out.println("PC: Aew! Encontrei a casa de posicao "+(posicaoBase.getX()+1)+"."+(posicaoBase.getY()+1)+"...");
		return posicaoBase;
	}

	//Recupera a primeira casa incompleta do tabuleiro
	private Posicao getPosicaoIncompleta(Tabuleiro tabuleiro) {
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(tabuleiro.getCasa(i, j).getIdentificada() && !this.getCompletude(i, j, tabuleiro)) {
					return new Posicao(i,j);//verificar condicao
				}
			}
		}
		return null;
	}

	public Posicao getMaiorPosicaoMaiorCasaCompleta(Tabuleiro tabuleiro) {
		Posicao posicaoBase = new Posicao(-1, -1);
		posicaoBase = this.getPosicaoCompleta(tabuleiro);
		if(posicaoBase == null) return posicaoBase;
		int x = posicaoBase.getX();
		int y = posicaoBase.getY();
		System.out.println("PC: Achei uma casa na posicao "+(x+1)+"."+(y+1));
		System.out.println("PC: Procurando outra casa completa e jogavel com maior adjacencia...");
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(i != x || j != y) {
					if(this.getCompletude(i, j, tabuleiro) && this.getJogavelAdjacente(i, j, tabuleiro) && (tabuleiro.getCasa(i, j).getNumeroBombasAdjacentes() > tabuleiro.getCasa(posicaoBase.getX(), posicaoBase.getY()).getNumeroBombasAdjacentes())) {
						posicaoBase.setX(i);
						posicaoBase.setY(j);
					}
				}
			}
		}
		if(posicaoBase.getX() == x && posicaoBase.getY() == y) System.out.println("PC: Aff! Nao encontrei...");
		else System.out.println("PC: Aew! Encontrei a casa de posicao "+(posicaoBase.getX()+1)+"."+(posicaoBase.getY()+1)+"...");
		return posicaoBase;
	}
	
	public Posicao sorteiaAdjacenciaCasaCompleta(Tabuleiro tabuleiro) {
		PosicaoCollection collection = new PosicaoCollection(8);
		Posicao posicao = this.getMaiorPosicaoMaiorCasaCompleta(tabuleiro);
		if(posicao == null) return posicao;
		int k = 0;
		int x = posicao.getX(); 
		int y = posicao.getY();
		for (int i = x-1; i < x+2; i++) {
			for (int j = y-1; j < y+2; j++) {
				if(tabuleiro.verificaValor(i) && tabuleiro.verificaValor(j) && !tabuleiro.getCasa(i, j).getIdentificada()) {
					posicao = new Posicao(i,j);
					collection.setPosicao(k, posicao);
					k++;
				}
			}
		}
		System.out.println("PC: Hum... Escolhendo uma da(s) "+k+" adjacencia(s) da casa de posicao "+(x+1)+"."+(y+1)+"...");
		boolean ok = false;
		posicao = new Posicao(-1,-1);
		Random numeroRandomico = new Random(); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Codigo repetido(JogadorPC e Tabuleiro)
		int index; 

		do {
			index = numeroRandomico.nextInt(tabuleiro.getTamanho()); //gera um inteiro randomico de 0 a tabuleiro.tamanho-1;
			if((index < k)) ok = true; //garante a escolha de uma posicao valida da colecao de posicoes
		} while(!ok);
		return collection.getPosicao(index);
	}

	public Posicao sorteiaAdjacenciaCasaIncompleta(Tabuleiro tabuleiro) {
		PosicaoCollection collection = new PosicaoCollection(8);
		Posicao posicao = this.getMaiorPosicaoMaiorCasaIncompleta(tabuleiro);
		if(posicao == null) return posicao;
		int k = 0;
		int x = posicao.getX(); 
		int y = posicao.getY();
		for (int i = x-1; i < x+2; i++) {
			for (int j = y-1; j < y+2; j++) {
				if(tabuleiro.verificaValor(i) && tabuleiro.verificaValor(j) && !tabuleiro.getCasa(i, j).getIdentificada()) {
					posicao = new Posicao(i,j);
					collection.setPosicao(k, posicao);
					k++;
				}
			}
		}
		System.out.println("PC: Hum... Escolhendo uma da(s) "+k+" adjacencia(s) da casa de posicao "+(x+1)+"."+(y+1)+"...");
		boolean ok = false;
		posicao = new Posicao(-1,-1);
		Random numeroRandomico = new Random(); //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<Codigo repetido(JogadorPC e Tabuleiro)
		int index; 
		do {
			index = numeroRandomico.nextInt(tabuleiro.getTamanho()); //gera um inteiro randomico de 0 a tabuleiro.tamanho-1;
			if((index < k)) ok = true; //garante a escolha de uma posicao valida da colecao de posicoes
		} while(!ok);
		return collection.getPosicao(index);
		
	}
	
	private Posicao getPosicaoCompleta(Tabuleiro tabuleiro) {
		for (int i = 0; i < tabuleiro.getTamanho(); i++) {
			for (int j = 0; j < tabuleiro.getTamanho(); j++) {
				if(this.getCompletude(i, j, tabuleiro) && this.getJogavelAdjacente(i, j, tabuleiro)) return new Posicao(i,j);
			}
		}
		return null;
	}
	
	
}

